﻿
//#include "../BasicLib/SpLock.h"
//#include "Database.h"
#include "../FacilityBaseLib/Container.h"
#include "../FacilityBaseLib/DateTime.h"
//#include "../FacilityBaseLib/Instrument.h"
//#include "../BasicLib/TinyThread/tinythread.h"
#include <thread>
using namespace std;
#include "DataFormat.h"


#ifdef _MSC_VER
#include <inttypes.h>
#endif
#ifdef WIN32

#include <direct.h>
#include <io.h>
#endif
#include "SelfDB.h"
#include <cassert>
#include <iostream>
using namespace std;

/////////////////////////////////////////////////////////////////////////////////////
// SelfDB strings

extern	char ml_dat[];
extern	char ml_dat[];
extern	char ml_sh_info[];
extern	char ml_sz_info[];
extern	char ml_sh_now[];
extern	char ml_sz_now[];
extern	char ml_sh_pyjc[];
extern	char ml_sz_pyjc[];
extern	char ml_sh_trace[];
extern	char ml_sz_trace[];
extern	char ml_sh_minute[];
extern	char ml_sz_minute[];

extern	char ml_data[];
extern	char ml_sh[];
extern	char ml_sz[];
extern	char ml_base[];
extern	char ml_month[];
extern	char ml_week[];
extern	char ml_day[];
extern	char ml_min5[];
extern	char ml_sh_base[];
extern	char ml_sz_base[];
extern	char ml_sh_month[];
extern	char ml_sz_month[];
extern	char ml_sh_week[];
extern	char ml_sz_week[];
extern	char ml_sh_day[];
extern	char ml_sz_day[];
extern	char ml_sh_min[];
extern	char ml_sz_min[];
extern	char ml_ext_base[];
extern	char ml_ext_month[];
extern	char ml_ext_week[];
extern	char ml_ext_day[];
extern	char ml_ext_min5[];

char self_ext_xdr[]		= ".dat";

char self_sh_xdr[]		= "data\\sh\\xdr\\";
char self_sz_xdr[]		= "data\\sz\\xdr\\";
char self_news[]		= "news\\";

char self_chna_xdr[]	= "data\\chna.pwr";		// 除权文件，与分析家格式相同
char self_chna_basetbl[]= "data\\shna.bst";		// 财务资料表

// 代码表文件
char self_sh_code[]		= "data\\shse.cod";		// 上海代码表
char self_sz_code[]		= "data\\szse.cod";		// 深圳代码表

// 行情缓存文件
char self_sh_report[]	= "data\\shse.rpt";		// 上海行情保存文件
char self_sz_report[]	= "data\\szse.rpt";		// 深圳行情保存文件
char self_sh_minute[]	= "data\\shse.min";		// 上海分时保存文件
char self_sz_minute[]	= "data\\szse.min";		// 深圳分时保存文件
char self_outline[]		= "data\\clkoutln.out";

/////////////////////////////////////////////////////////////////////////////////////
// SelfDB convertor

bool convert_CLK_DRDATA_to_DRDATA(DWORD dwMarket, const char *szCode, CLK_DRDATA * pdbdr, DRDATA * pdr)
{
	assert(pdbdr && pdr);
	if (NULL == pdbdr || NULL == pdr)
		return false;
	memset(pdr, 0, sizeof(DRDATA));

	pdr->m_dwMarket	= dwMarket;
	if (szCode)
		strncpy(pdr->m_szCode, szCode, min(sizeof(pdr->m_szCode)-1,strlen(szCode)));
	
	pdr->m_date	= pdbdr->date;
	DateTime	sptime;
	if (sptime.FromInstrumentTimeDay(pdr->m_date))
		pdr->m_time	= sptime.GetTime();

	pdr->m_fProfit	= (float)(pdbdr->bonus * 0.0001);
	pdr->m_fGive	= (float)(pdbdr->bonus_share * 0.001);
	pdr->m_fPei		= (float)(pdbdr->ration_share * 0.001);
	pdr->m_fPeiPrice= (float)(pdbdr->ration_value * 0.001);

	return true;
}

bool convert_DRDATA_to_CLK_DRDATA(DRDATA * pdr, CLK_DRDATA * pdbdr)
{
	assert(pdbdr && pdr);
	if (NULL == pdbdr || NULL == pdr)
		return false;
	memset(pdbdr, 0, sizeof(CLK_DRDATA));

	pdbdr->date	= pdr->m_date;

	pdbdr->bonus		= (DWORD)(pdr->m_fProfit * 10000);
	pdbdr->bonus_share	= (DWORD)(pdr->m_fGive * 1000);
	pdbdr->ration_share	= (DWORD)(pdr->m_fPei * 1000);
	pdbdr->ration_value	= (DWORD)(pdr->m_fPeiPrice * 1000);
	return true;
}

bool convert_FXJ_DRDATA_to_DRDATA(DWORD dwMarket, const char *szCode, FXJ_DRDATA * pfxjdr, DRDATA * pdr)
{
	assert(pfxjdr && pdr);
	if (NULL == pfxjdr || NULL == pdr)
		return false;
	memset(pdr, 0, sizeof(DRDATA));

	pdr->m_dwMarket	= dwMarket;
	if (szCode)
		strncpy(pdr->m_szCode, szCode, min(sizeof(pdr->m_szCode)-1,strlen(szCode)));
	
	pdr->m_time	= pfxjdr->m_time;
	DateTime	sptime(pdr->m_time);
	pdr->m_date	= sptime.ToInstrumentTimeDay();

	pdr->m_fProfit	= pfxjdr->m_fProfit;
	pdr->m_fGive	= pfxjdr->m_fGive;
	pdr->m_fPei		= pfxjdr->m_fPei;
	pdr->m_fPeiPrice= pfxjdr->m_fPeiPrice;

	return true;
}

double StringToDouble(const char *sz, int nLen)
{
	char	szTemp[32];
	if (NULL == sz || nLen >= sizeof(szTemp))
	{
		assert(false);
		return 0;
	}

	memset(szTemp, 0, sizeof(szTemp));
	memcpy(szTemp, sz, nLen);

	int	nPos	= 0;
	while(isspace(szTemp[nPos]) && nPos < nLen)
		nPos ++;
	if (nPos == nLen)
		return 0;
	return atof(&szTemp[nPos]);
}

bool convert_TDX_BASEDATA_to_BASEDATA(TDX_BASEDATA * ptdxbd, BASEDATA *pbd)
{
	assert(ptdxbd && pbd);
	//if (NULL == ptdxbd || NULL == pbd)
	//	return false;
	//memset(pbd, 0, sizeof(BASEDATA));
	//
	////pbd->m_dwMarket	= CInstrument::marketCHNA;
	//strncpy(pbd->m_szCode, ptdxbd->m_szCode, min(sizeof(pbd->m_szCode)-1,sizeof(ptdxbd->m_szCode)));

	//CInstrumentInfo	info;
	//if (AfxGetStockContainer().GetInstrumentInfo()(pbd->m_szCode, &info))
	//{
	//	int	nSize	= info.m_basedata.GetSize();
	//	if (nSize > 0)
	//		memcpy(pbd, &(info.m_basedata.ElementAt(nSize-1)), sizeof(BASEDATA));
	//	pbd->m_dwMarket	= info.GetMarket();
	//}
	//
	//// char	m_szDomain[STKLIB_MAX_DOMAIN];		// 板块
	//// char	m_szProvince[STKLIB_MAX_PROVINCE];	// 省份

	//if ('0' == ptdxbd->m_szMarket)
	//	pbd->m_dwMarket	= CInstrument::marketSZSE;
	//else if ('1' == ptdxbd->m_szMarket)
	//	pbd->m_dwMarket	= CInstrument::marketSHSE;

	//pbd->m_date	= (DWORD)StringToDouble(ptdxbd->m_szDate_modified, sizeof(ptdxbd->m_szDate_modified));
	//pbd->m_reporttype	= CInstrument::reportAnnals;	// 报告类型：年报、中报、季报
	//CSPTime	sptime;
	//if (sptime.FromStockTimeDay(pbd->m_date))
	//{
	//	pbd->m_time	= sptime.GetTime();
	//	int nMonth = sptime.GetMonth();
	//	if (nMonth >= 4 && nMonth <= 6)
	//		pbd->m_reporttype	= CInstrument::reportQuarter;
	//	else if (nMonth >= 7 && nMonth <= 9)
	//		pbd->m_reporttype	= CInstrument::reportMid;
	//	else if (nMonth >= 10 && nMonth <= 12)
	//		pbd->m_reporttype	= CInstrument::reportQuarter3;
	//}

	//// float	m_fErate_dollar;			// 当期美元汇率
	//// float	m_fErate_hkdollar;			// 当期港币汇率

	//// ★偿债能力
	//// float	m_fRatio_liquidity;			// 流动比率
	//// float	m_fRatio_quick;				// 速动比率
	//// float	m_fVelocity_receivables;	// 应收帐款周率
	//
	//// ★经营能力
	//// float	m_fVelocity_merchandise;	// 存货周转率
	//pbd->m_fMain_income			= (float)StringToDouble(ptdxbd->m_szMain_income, sizeof(ptdxbd->m_szMain_income)) * 1000;
	//// float	m_fCash_ps;					// 每股净现金流量
	//
	//// ★资本结构
	//pbd->m_datebegin			= (DWORD)StringToDouble(ptdxbd->m_szDate_begin, sizeof(ptdxbd->m_szDate_begin));
	//pbd->m_fShare_count_total	= (float)StringToDouble(ptdxbd->m_szShare_count_total, sizeof(ptdxbd->m_szShare_count_total)) * 10000;
	//pbd->m_fShare_count_a		= (float)StringToDouble(ptdxbd->m_szShare_count_currency, sizeof(ptdxbd->m_szShare_count_currency)) * 10000;
	//pbd->m_fShare_count_b		= (float)StringToDouble(ptdxbd->m_szShare_count_b, sizeof(ptdxbd->m_szShare_count_b)) * 10000;
	//pbd->m_fShare_count_h		= (float)StringToDouble(ptdxbd->m_szShare_count_h, sizeof(ptdxbd->m_szShare_count_h)) * 10000;
	//pbd->m_fShare_count_national= (float)StringToDouble(ptdxbd->m_szShare_count_national, sizeof(ptdxbd->m_szShare_count_national)) * 10000;
	//pbd->m_fShare_count_corp	= (float)StringToDouble(ptdxbd->m_szShare_count_corp, sizeof(ptdxbd->m_szShare_count_corp)) * 10000;
	//if (CInstrument::typeshB == info.GetType() || CInstrument::typeszB == info.GetType())	// A B股 交换
	//{
	//	float	fTemp	= pbd->m_fShare_count_a;
	//	pbd->m_fShare_count_a	= pbd->m_fShare_count_b;
	//	pbd->m_fShare_count_b	= fTemp;
	//}
	//
	//if (pbd->m_fShare_count_total > 1e-4)
	//	pbd->m_fProfit_psud		= (float)StringToDouble(ptdxbd->m_szProfit_ud, sizeof(ptdxbd->m_szProfit_ud)) * 1000 / pbd->m_fShare_count_total;
	//pbd->m_fAsset				= (float)StringToDouble(ptdxbd->m_szAsset, sizeof(ptdxbd->m_szAsset)) * 1000;
	//if (pbd->m_fAsset > 1e-4)
	//{
	//	pbd->m_fRatio_holderright= (float)(100 * StringToDouble(ptdxbd->m_szNet_asset, sizeof(ptdxbd->m_szNet_asset)) * 1000 / pbd->m_fAsset);
	//	pbd->m_fRatio_longdebt	= (float)(100 * StringToDouble(ptdxbd->m_szDebt_long, sizeof(ptdxbd->m_szDebt_long)) * 1000 / pbd->m_fAsset);
	//	pbd->m_fRatio_debt		= (float)(100 * (StringToDouble(ptdxbd->m_szDebt_long, sizeof(ptdxbd->m_szDebt_long)) * 1000 / pbd->m_fAsset
	//									+ StringToDouble(ptdxbd->m_szDebt_long, sizeof(ptdxbd->m_szDebt_long)) * 1000 / pbd->m_fAsset));
	//}

	//// ★投资收益能力
	//pbd->m_fNetasset_ps_regulate= (float)StringToDouble(ptdxbd->m_szNet_asset_ps_regulate, sizeof(ptdxbd->m_szNet_asset_ps_regulate));
	//if (pbd->m_fShare_count_total > 1e-4)
	//{
	//	pbd->m_fNetasset_ps		= (float)StringToDouble(ptdxbd->m_szNet_asset, sizeof(ptdxbd->m_szNet_asset)) * 1000 / pbd->m_fShare_count_total;
	//	pbd->m_fEps				= (float)StringToDouble(ptdxbd->m_szNet_profit, sizeof(ptdxbd->m_szNet_profit)) * 1000 / pbd->m_fShare_count_total;
	//	pbd->m_fEps_deduct		= (float)(pbd->m_fEps - StringToDouble(ptdxbd->m_szOut_profit, sizeof(ptdxbd->m_szOut_profit)) * 1000 / pbd->m_fShare_count_total);
	//}

	//pbd->m_fNet_profit			= (float)StringToDouble(ptdxbd->m_szNet_profit, sizeof(ptdxbd->m_szNet_profit)) * 1000;
	//pbd->m_fMain_profit			= (float)StringToDouble(ptdxbd->m_szMain_profit, sizeof(ptdxbd->m_szMain_profit)) * 1000;
	//pbd->m_fTotal_profit		= (float)StringToDouble(ptdxbd->m_szTotal_profit, sizeof(ptdxbd->m_szTotal_profit)) * 1000;

	//// ★盈利能力
	//if (pbd->m_fMain_income > 1e-4)
	//	pbd->m_fProfit_margin	= (float)(100 * pbd->m_fMain_profit / pbd->m_fMain_income);
	//if (pbd->m_fNetasset_ps > 1e-4)
	//	pbd->m_fNetasset_yield	= (float)(100 * pbd->m_fEps / pbd->m_fNetasset_ps);

	return true;
}

bool convert_FXJ_BASEDATA_to_BASEDATA(FXJ_BASEDATA * pfxjbd, BASEDATA *pbd, DWORD dwDate)
{
	assert(pfxjbd && pbd);
//	if (NULL == pfxjbd || NULL == pbd)
//		return false;
//	memset(pbd, 0, sizeof(BASEDATA));
//	
//	pbd->m_dwMarket	= CInstrument::marketCHNA;
//	strncpy(pbd->m_szCode, pfxjbd->m_szCode, min(sizeof(pbd->m_szCode)-1,sizeof(pfxjbd->m_szCode)));
//
//	CInstrumentInfo	info;
//	if (AfxGetStockContainer().GetInstrumentInfo()(pbd->m_szCode, &info))
//	{
//		int	nSize	= info.m_basedata.GetSize();
//		if (nSize > 0)
//			memcpy(pbd, &(info.m_basedata.ElementAt(nSize-1)), sizeof(BASEDATA));
//		pbd->m_dwMarket	= info.GetMarket();
//	}
//	
//	// char	m_szDomain[STKLIB_MAX_DOMAIN];		// 板块
//	// char	m_szProvince[STKLIB_MAX_PROVINCE];	// 省份
//
//	if ('ZS' == pfxjbd->m_wMarket)
//		pbd->m_dwMarket	= CInstrument::marketSZSE;
//	else if ('HS' == pfxjbd->m_wMarket)
//		pbd->m_dwMarket	= CInstrument::marketSHSE;
//
//	pbd->m_date	= dwDate;
//	pbd->m_reporttype	= CInstrument::reportAnnals;	// 报告类型：年报、中报、季报
//	CSPTime	sptime;
//	if (sptime.FromStockTimeDay(pbd->m_date))
//	{
//		pbd->m_time	= sptime.GetTime();
//		int nMonth = sptime.GetMonth();
//		if (nMonth >= 4 && nMonth <= 6)
//			pbd->m_reporttype	= CInstrument::reportQuarter;
//		else if (nMonth >= 7 && nMonth <= 9)
//			pbd->m_reporttype	= CInstrument::reportMid;
//		else if (nMonth >= 10 && nMonth <= 12)
//			pbd->m_reporttype	= CInstrument::reportQuarter3;
//	}
//
//	// float	m_fErate_dollar;			// 当期美元汇率
//	// float	m_fErate_hkdollar;			// 当期港币汇率
//
//	// ★偿债能力
//	// float	m_fRatio_liquidity;			// 流动比率
//	// float	m_fRatio_quick;				// 速动比率
//	// float	m_fVelocity_receivables;	// 应收帐款周率
//	
//	// ★经营能力
//	// float	m_fVelocity_merchandise;	// 存货周转率
//	pbd->m_fMain_income			= pfxjbd->m_fData[21]*1000;
//	// float	m_fCash_ps;					// 每股净现金流量
//	
//	// ★盈利能力
//	if (pbd->m_fMain_income > 1e-4)
//		pbd->m_fProfit_margin	= (float)(100 * pfxjbd->m_fData[22]*1000 / pbd->m_fMain_income);
//	pbd->m_fNetasset_yield		= pfxjbd->m_fData[38];
//
//	// ★资本结构
//	// DWORD	m_datebegin					// 上市日期
//	pbd->m_fShare_count_total	= pfxjbd->m_fData[2]*10000;
//	pbd->m_fShare_count_a		= pfxjbd->m_fData[8]*10000;
//	pbd->m_fShare_count_b		= pfxjbd->m_fData[6]*10000;
//	pbd->m_fShare_count_h		= pfxjbd->m_fData[7]*10000;
//	pbd->m_fShare_count_national= pfxjbd->m_fData[3]*10000;
//	pbd->m_fShare_count_corp	= pfxjbd->m_fData[5]*10000;
////	if (CInstrument::typeshB == info.GetType() || CInstrument::typeszB == info.GetType())	// A B股 交换
////	{
////		float	fTemp	= pbd->m_fShare_count_a;
////		pbd->m_fShare_count_a	= pbd->m_fShare_count_b;
////		pbd->m_fShare_count_b	= fTemp;
////	}
//	
//	pbd->m_fProfit_psud			= pfxjbd->m_fData[33];
//	pbd->m_fAsset				= pfxjbd->m_fData[11]*1000;
//	pbd->m_fRatio_holderright	= pfxjbd->m_fData[37];
//	if (pbd->m_fAsset > 1e-4)
//		pbd->m_fRatio_longdebt	= (float)(100 * pfxjbd->m_fData[17] * 1000 / pbd->m_fAsset);
//	pbd->m_fRatio_debt			= 100 - pbd->m_fRatio_holderright;
//
//	// ★投资收益能力
//	pbd->m_fNetasset_ps			= pfxjbd->m_fData[35];
//	pbd->m_fNetasset_ps_regulate= pfxjbd->m_fData[36];
//	pbd->m_fEps					= pfxjbd->m_fData[34];
//	if (pbd->m_fShare_count_total > 1e-4)
//		pbd->m_fEps_deduct		= (float)(pbd->m_fEps - pfxjbd->m_fData[25] * 1000 / pbd->m_fShare_count_total);
//
//	pbd->m_fNet_profit			= pfxjbd->m_fData[31]*1000;
//	pbd->m_fMain_profit			= pfxjbd->m_fData[22]*1000;
//	pbd->m_fTotal_profit		= pfxjbd->m_fData[29]*1000;
//
	return true;
}

DWORD ReadMinute(instrument* pstock,const char* lpszFileName)
{
	assert(pstock && pstock->GetInstrumentInfo().is_valid());
	if (!pstock || !pstock->GetInstrumentInfo().is_valid())
		return 0;

	minute_container& aMinute = pstock->GetMinute();
	aMinute.clear();

	CTSKFile file;
	if (file.Open(lpszFileName))
	{
		DWORD dwDataRecordCount = file.GetDataRecordCount(pstock->GetInstrumentInfo().ExchangeID, pstock->GetInstrumentID());
		aMinute.resize(dwDataRecordCount);
		DWORD dwCount = file.LoadDataRecord(pstock->GetInstrumentInfo().ExchangeID, pstock->GetInstrumentID(), aMinute.data(), sizeof(MINUTE), dwDataRecordCount);
		aMinute.resize(dwCount);

		aMinute.sort();
		//aMinute.RemoveDirty();
	}

	return aMinute.size();
}

//=============================================================================
// CTSKFile

CTSKFile::CTSKFile()
{
	Close();
}

CTSKFile::~CTSKFile()
{
	Close();
}

bool CTSKFile::Open(const char* lpszFileName)
{
	Close();
	m_file.open(lpszFileName, ios::out|ios::binary|ios::in);
	if (!m_file.is_open())
		return false;
	m_filename=lpszFileName;
	m_file.seekg(0,fstream::beg);
	m_file.read((char*)&m_header, sizeof(m_header));
	streamsize bytes_read=m_file.gcount();
	if (bytes_read!= sizeof(m_header))
	{
		return false;
	}
	if (m_header.m_dwMagic != CLK_FHEADER_MAGIC)
	{
		assert(false);
		return false;
	}
	return true;
}

void CTSKFile::Close()
{
	if (m_file.is_open())
	{
		m_header.m_time = time(NULL);
		m_file.seekg(0, fstream::beg);
		m_file.write((char*)&m_header, sizeof(m_header));
		m_file.close();
	}
	memset(&m_header, 0, sizeof(m_header));
	memset(&m_CurIndexRecord, 0, sizeof(m_CurIndexRecord));
	m_filename="";
	m_dwPosCurIndex	= -1;
}

// 创建空的数据文件
bool CTSKFile::BuildEmptyFile(const char* lpszFileName,
						DWORD dwDataType,	// 数据分类说明，see CInstrument::DataType
						char* dwMarket,			// 市场，see CInstrument::StockMarket，如果文件包含多个市场，则=0无效
						DWORD dwIndexRecordCount,	// 索引区记录单元个数
						DWORD dwRecordPerBlock,		// 每个Block的记录数
						bool bRebuildIfExists)
{
	assert(NULL != lpszFileName && strlen(lpszFileName) > 0);
	if (NULL == lpszFileName || strlen(lpszFileName) <= 0)
		return false;

	// 如果文件存在，则不新建
	if (!bRebuildIfExists && 0 == access(lpszFileName,0))
		return true;
	//填充文件头
	CLK_FHEADER	header;
	memset(&header, 0,sizeof(header));
	header.m_dwMagic	= CLK_FHEADER_MAGIC;
	header.m_dwVerMajor	= CLK_FHEADER_VERMAJOR;
	header.m_dwVerMinor	= CLK_FHEADER_VERMINOR;
	strcpy(header.m_szDescript, "CLKing Stock File Structure. See www.ninebulls.com for more information.");
	header.m_dwDataType	= dwDataType;
	strcpy(header.m_dwMarket,dwMarket);
	//时间戳
	header.m_time		= time(NULL);
	
	// 索引区信息
	header.m_dwPosFirstIndex	= sizeof(header);
	//每个索引块的大小;
	header.m_dwIndexRecordSize	= sizeof(CLK_INDEXRECORD);
	//索引块的个数
	header.m_dwIndexRecordCount	= dwIndexRecordCount;

	header.m_dwStockCount		= 0;

	// 数据区信息
	switch (dwDataType)
	{
	case instrument::dataReport:
		header.m_dwDataRecordSize	= sizeof(Tick);
		break;
	case instrument::dataMinute:
		header.m_dwDataRecordSize	= sizeof(MINUTE);
		break;
	case instrument::dataK:
		header.m_dwDataRecordSize	= sizeof(KDATA);
	default:
		assert(false);
		return false;
	}
	header.m_dwRecordPerBlock	= dwRecordPerBlock;
	header.m_dwBlockSize		= sizeof(CLK_BLOCKHEADER) + header.m_dwDataRecordSize * header.m_dwRecordPerBlock;
	header.m_dwPosFirstBlock	= sizeof(CLK_FHEADER) + header.m_dwIndexRecordSize * header.m_dwIndexRecordCount;
	header.m_dwPosFirstBlankBlock	= -1;

	fstream	file;
	file.open(lpszFileName,ios::out);
	if (!file.is_open())
	{
		assert(false);
		return false;
	}
	file.write((char*)&header, sizeof(header));

	for (DWORD i=0; i<header.m_dwIndexRecordCount; i++)
	{
		CLK_INDEXRECORD	index;
		memset(&index, 0, sizeof(index));
		index.m_dwMagic			= CLK_INDEXRECORD_MAGIC;
		index.m_dwPosFirstBlock	= -1;
		file.write((char*)&index, sizeof(index));
	}
	
	file.flush();
	file.close();
	return true;
}

// 重新创建，如果日期不是tmNow;
bool CTSKFile::RemoveFileIfOutoftime(const char* lpszFileName, time_t tmNow)
{
	assert(NULL!=lpszFileName && strlen(lpszFileName) > 0);
	if (NULL==lpszFileName || strlen(lpszFileName) <= 0)
		return false;

	CTSKFile	file;
	if (file.Open(lpszFileName))
	{
		DateTime	ft(file.m_header.m_time);
		DateTime	tNow(tmNow);
		
		if (CLK_FHEADER_VERMAJOR == file.m_header.m_dwVerMajor 
			&& CLK_FHEADER_VERMINOR == file.m_header.m_dwVerMinor)	// 版本相同
		{
			if (ft.GetYear() == tNow.GetYear() && ft.GetMonth() == tNow.GetMonth() && ft.GetDay() == tNow.GetDay())
				return false;
			int	nDayOfWeek = tNow.GetDayOfWeek();
			if (1 == nDayOfWeek || 7 == nDayOfWeek)
				return false;

			bool	bEmpty	= false; // file.EmptyAll();
			file.Close();

			if (!bEmpty)
				return ::remove(lpszFileName);
			return true;
		}
		else
		{
			file.Close();
			return ::remove(lpszFileName);
		}
	}

	return false;
}

static std::mutex g_mutexClkFile;

bool CTSKFile::EmptyAll()
{
    std::unique_lock<std::mutex> locker(g_mutexClkFile);

// 	assert(CFile::hFileNull != m_file.m_hFile);
// 	if (CFile::hFileNull == m_file.m_hFile)
// 		return false;

	// 顺序寻找
	DWORD	dwCount	= 0;
	for (DWORD i=0; i<m_header.m_dwIndexRecordCount; i++)
	{
		DWORD	dwPosIndex	= m_header.m_dwPosFirstIndex + m_header.m_dwIndexRecordSize * i;
		if ((int)m_file.tellp() != dwPosIndex)
			m_file.seekp(dwPosIndex, fstream::beg);

		CLK_INDEXRECORD	index;
		if (/*sizeof(index) != */!m_file.read((char*)&index,sizeof(index)))
			return false;
		if (CLK_INDEXRECORD_MAGIC != index.m_dwMagic)
			return false;
		if (strlen(index.m_szCode) <= 0)
			continue;
		
		EmptyBlockChain(index.m_dwPosFirstBlock);
		index.m_dwDataRecordCountTotal	= 0;
		m_file.seekp(dwPosIndex, fstream::beg);
		m_file.write((char*)&index, sizeof(index));

		dwCount	++;
	}

	m_file.flush();
//	ASSERT(dwCount == m_header.m_dwStockCount);
	return dwCount > 0; // == m_header.m_dwStockCount;
}

// 保存数据，并修改相应索引信息
DWORD CTSKFile::StoreDataRecord(char* dwMarket, const char * szCode,
							void * pData, DWORD dwDataElementSize, DWORD dwDataElementCount,
							bool bOverWrite)	// 返回成功保存记录数
{
    std::unique_lock<std::mutex> locker(g_mutexClkFile);

	CLK_INDEXRECORD	index;
	DWORD	dwPosIndexFind	= -1;
	if (!GetDataInfo(dwMarket, szCode, index, dwPosIndexFind, true))
		return 0;

	if (bOverWrite)
	{
		EmptyBlockChain(index.m_dwPosFirstBlock);
		index.m_dwDataRecordCountTotal	= 0;
	}

	if (-1 == index.m_dwPosFirstBlock || 0 == index.m_dwPosFirstBlock)
		index.m_dwPosFirstBlock	= GetFirstBlankBlockPos(true, true);
	DWORD	dwCount = WriteData(index.m_dwPosFirstBlock, pData, dwDataElementSize, dwDataElementCount, false);
	index.m_dwDataRecordCountTotal	+= dwCount;
	SetDataInfo(dwPosIndexFind, index, false);

	return dwCount;
}

// 得到某一股票的数据记录数
DWORD CTSKFile::GetDataRecordCount(char* dwMarket, const char * szCode)
{
    std::unique_lock<std::mutex> locker(g_mutexClkFile);

	CLK_INDEXRECORD	index;
	DWORD	dwPosIndexFind	= -1;
	if (GetDataInfo(dwMarket, szCode, index, dwPosIndexFind, false))
		return index.m_dwDataRecordCountTotal;
	return 0;
}

// 读取某一股票的数据记录
DWORD CTSKFile::LoadDataRecord(char* dwMarket, const char * szCode,
							void * pData, DWORD dwDataElementSize, DWORD dwMaxDataElement)// 返回成功读取记录数
{
    std::unique_lock<std::mutex> locker(g_mutexClkFile);

//	ASSERT(CFile::hFileNull != m_file.m_hFile);
// 	if (CFile::hFileNull == m_file.m_hFile)
// 		return 0;

	CLK_INDEXRECORD	index;
	DWORD	dwPosIndexFind	= -1;
	if (!GetDataInfo(dwMarket, szCode, index, dwPosIndexFind, false))
		return 0;

	if (dwMaxDataElement < index.m_dwDataRecordCountTotal)
		return 0;

	return ReadData(index.m_dwPosFirstBlock, pData, dwDataElementSize, dwMaxDataElement);
}

DWORD CTSKFile::Hash(const char* key, DWORD dwMax)
{
	DWORD dwHash = 0;
	while (*key)
		dwHash = (dwHash<<5) + dwHash + *key++;
	return dwHash % dwMax;
// 	DWORD hash = 1315423911;
// 	while(*key)  
// 	{  
// 		hash ^= ((hash << 5) + (*key) + (hash >> 2));  
// 	}  
// 	return hash;
}

// 得到某一股票的索引区信息，如果bAddIfNotExists并且不存在，则添加;
bool CTSKFile::GetDataInfo(	char* dwMarket, const char * szCode, CLK_INDEXRECORD & idxRet, DWORD & dwPosIndexFind, bool bAddIfNotExists)
{
	// 是否当前Cache
	if (strcmp(m_CurIndexRecord.m_dwMarket,dwMarket)==0
		&& 0 == strcmp(m_CurIndexRecord.m_szCode, szCode))
	{
		idxRet			= m_CurIndexRecord;
		dwPosIndexFind	= m_dwPosCurIndex;
		return true;
	}
	//使用Hash计算位置;
	DWORD	posBegin	= Hash(szCode, m_header.m_dwIndexRecordCount);
	// Hash顺序寻找;
	for (DWORD i=posBegin; i<m_header.m_dwIndexRecordCount; i++)
	{
		DWORD	dwPosIndex	= m_header.m_dwPosFirstIndex + m_header.m_dwIndexRecordSize * i;
		if ((int)m_file.tellg() != dwPosIndex)
			m_file.seekg(dwPosIndex, fstream::beg);

		CLK_INDEXRECORD	index;
		m_file.read((char*)&index,sizeof(index));
		if (sizeof(index) != m_file.gcount() || CLK_INDEXRECORD_MAGIC != index.m_dwMagic)
		{
			assert(false);
			return false;
		}
		if (0==strcmp(dwMarket,index.m_dwMarket)&&
			0 == strcmp(szCode, index.m_szCode))
		{
			idxRet				= index;
			dwPosIndexFind		= dwPosIndex;
			m_CurIndexRecord	= index;
			m_dwPosCurIndex		= dwPosIndex;
			return true;
		}
		if (0 == strlen(index.m_szCode))
		{
			if (bAddIfNotExists)
			{
				strcpy(index.m_dwMarket,dwMarket);
				strncpy(index.m_szCode, szCode, min(sizeof(index.m_szCode)-1,strlen(szCode)));
				index.m_dwDataRecordCountTotal	= 0;
				index.m_dwPosFirstBlock	= GetFirstBlankBlockPos(true, true);

				m_file.seekp(dwPosIndex, fstream::beg);
				m_file.write((char*)&index, sizeof(index));

				// 文件头
				m_header.m_dwStockCount	+= 1;
				m_file.seekp(0, fstream::beg);
				m_file.write((char*)&m_header, sizeof(m_header));
				m_file.flush();

				// return
				idxRet				= index;
				dwPosIndexFind		= dwPosIndex;
				m_CurIndexRecord	= index;
				m_dwPosCurIndex		= dwPosIndex;
				return true;
			}
			return false;
		}

		// 循环
		if (m_header.m_dwIndexRecordCount-1 == i)
			i = -1;
		if (posBegin-1 == i)
			break;
	}

	return false;
}

// 保存某一股票的索引区信息
bool CTSKFile::SetDataInfo(	DWORD dwPosIndex, CLK_INDEXRECORD idx, bool bFlush)
{
// 	if (CFile::hFileNull == m_file.m_hFile)
// 		return false;

	// 是否当前Cache
	if (0==strcmp(m_CurIndexRecord.m_dwMarket,idx.m_dwMarket)
		&& 0 == strcmp(m_CurIndexRecord.m_szCode, idx.m_szCode))
	{
		m_CurIndexRecord	= idx;
	}

	if (-1 != dwPosIndex)
	{
		m_file.seekp(dwPosIndex, fstream::beg);
		m_file.write((char*)&idx, sizeof(idx));
		if (bFlush)
			m_file.flush();
		return true;
	}
	return true;
}

// 得到某一空数据块
DWORD CTSKFile::GetFirstBlankBlockPos(bool bAddIfNotExists, bool bUseIt)
{
	DWORD	dwPosBlock	= m_header.m_dwPosFirstBlankBlock;
	if (-1 != dwPosBlock && 0 != dwPosBlock)
	{
		m_file.seekg(dwPosBlock, fstream::beg);
		
		CLK_BLOCKHEADER	bheader;
		m_file.read((char*)&bheader,sizeof(bheader));
		if (sizeof(bheader) == m_file.gcount())
		{
			assert(CLK_BLOCKHEADER_MAGIC == bheader.m_dwMagic);
			assert(!bheader.m_bUsed);

			if (bUseIt)
			{
				bheader.m_bUsed	= bUseIt;
				bheader.m_dwDataRecordCount	= 0;
				bheader.m_dwPosNextBlock	= -1;
				m_file.seekp(dwPosBlock, fstream::beg);
				m_file.write((char*)&bheader, sizeof(bheader));
			
				m_header.m_dwPosFirstBlankBlock	= bheader.m_dwPosNextBlock;
				m_file.seekp(0, fstream::beg);
				m_file.write((char*)&m_header, sizeof(m_header));
				// m_file.Flush();
			}
			return dwPosBlock;
		}
	}

	// Add
	if (bAddIfNotExists)
	{
		assert(bUseIt);	// Must Use It

		DWORD	dwDataSize = m_header.m_dwDataRecordSize*m_header.m_dwRecordPerBlock;
		if (dwDataSize <= 0)
			return -1;

		m_file.seekp(0,fstream::end);
		dwPosBlock	= m_file.tellp();

		CLK_BLOCKHEADER	bheader;
		memset(&bheader, 0, sizeof(bheader));
		bheader.m_dwMagic	= CLK_BLOCKHEADER_MAGIC;
		bheader.m_bUsed		= bUseIt;
		bheader.m_dwPosNextBlock	= -1;
		bheader.m_dwPosFirstRecord	= dwPosBlock + sizeof(bheader);
		m_file.write((char*)&bheader, sizeof(bheader));
		char	* temp	= new char[dwDataSize];
		if (!temp)
			return -1;
		memset(temp, 0, m_header.m_dwDataRecordSize);
		m_file.write(temp, dwDataSize);
		delete	[] temp;
		m_file.flush();
	}

	return dwPosBlock;
}

// 清空数据Block链中的数据，并将除第一个Block外的其他Block置为未用
DWORD CTSKFile::EmptyBlockChain(DWORD dwPosFirstBlock)
{
// 	ASSERT(CFile::hFileNull != m_file.m_hFile);
// 	if (CFile::hFileNull == m_file.m_hFile)
// 		return false;

	DWORD	dwCount	= 0;
	DWORD	dwPosBlock	= dwPosFirstBlock;

	while(-1 != dwPosBlock && 0 != dwPosBlock)
	{
		m_file.seekg(dwPosBlock, fstream::beg);

		DWORD	dwPosNextBlock	= -1;
		CLK_BLOCKHEADER	bheader;
		if (/*sizeof(bheader) != */!m_file.read((char*)&bheader,sizeof(bheader))
			|| CLK_BLOCKHEADER_MAGIC != bheader.m_dwMagic)
		{
			assert(false);
		}
		else
		{
			dwPosNextBlock	= bheader.m_dwPosNextBlock;
		}

		// Empty it
		bheader.m_bUsed	= (dwPosFirstBlock == dwPosBlock);	// 第一块继续使用
		bheader.m_dwDataRecordCount	= 0;
		bheader.m_dwPosNextBlock	= -1;
		if (!bheader.m_bUsed)
			bheader.m_dwPosNextBlock	= m_header.m_dwPosFirstBlankBlock;
		m_file.seekp(dwPosBlock, fstream::beg);
		m_file.write((char*)&bheader, sizeof(bheader));
		
		// 加入Blank Block Chain
		if (!bheader.m_bUsed)
		{
			m_header.m_dwPosFirstBlankBlock	= dwPosBlock;
			m_file.seekp(0, fstream::beg);
			m_file.write((char*)&m_header, sizeof(m_header));
		}
		// m_file.Flush();
		dwCount	++;

		dwPosBlock	= dwPosNextBlock;
	}
	
	return dwCount;
}

// 读数据记录
DWORD CTSKFile::ReadData(DWORD dwPosBlock, void * pData, DWORD dwDataElementSize, DWORD dwMaxDataElement)
{

	if (NULL == pData || dwMaxDataElement == 0)
		return 0;

	DWORD	dwCount	= 0;

	while(-1 != dwPosBlock && 0 != dwPosBlock)
	{
		m_file.seekg(dwPosBlock, fstream::beg);

		CLK_BLOCKHEADER	bheader;
		m_file.read((char*)&bheader,sizeof(bheader));
		if (sizeof(bheader) != m_file.gcount()
			|| CLK_BLOCKHEADER_MAGIC != bheader.m_dwMagic)
		{
			assert(false);
			return dwCount;
		}
		
		for (DWORD i=0; i<bheader.m_dwDataRecordCount; i++)
		{
			DWORD	dwPos	= bheader.m_dwPosFirstRecord + i * m_header.m_dwDataRecordSize;
			if ((int)m_file.tellg() != dwPos)
				m_file.seekg(dwPos, fstream::beg);
			m_file.read(((char *)pData)+dwDataElementSize*dwCount, min(dwDataElementSize,m_header.m_dwDataRecordSize));
			dwCount ++;
			if (dwCount >= dwMaxDataElement)
				return dwCount;
		}
		
		dwPosBlock	= bheader.m_dwPosNextBlock;
	}
	
	return dwCount;
}

// 写数据记录
DWORD CTSKFile::WriteData(DWORD dwPosBlock, void * pData, DWORD dwDataElementSize, DWORD dwDataElementCount, bool bFlush)
{
	assert(-1 != dwPosBlock && 0 != dwPosBlock);
	if (-1 == dwPosBlock || 0 == dwPosBlock)
		return 0;
	DWORD	dwCount	= 0;
	while(dwCount < dwDataElementCount && -1 != dwPosBlock && 0 != dwPosBlock)
	{
		m_file.seekg(dwPosBlock, fstream::beg);

		CLK_BLOCKHEADER	bheader;
		m_file.read((char*)&bheader,sizeof(bheader));
		if (sizeof(bheader) !=m_file.gcount()
			|| CLK_BLOCKHEADER_MAGIC != bheader.m_dwMagic)
		{
			assert(false);
			return dwCount;
		}

		if (-1 != bheader.m_dwPosNextBlock && 0 != bheader.m_dwPosNextBlock)
		{
			assert(bheader.m_dwDataRecordCount == m_header.m_dwRecordPerBlock);
			if (bheader.m_dwDataRecordCount == m_header.m_dwRecordPerBlock)
			{
				dwPosBlock	= bheader.m_dwPosNextBlock;
				continue;
			}
		}
		//m_file.seekp(0,fstream::cur);
		// Write
		DWORD	dwCountOld	= dwCount;
		for (DWORD i=bheader.m_dwDataRecordCount; i<m_header.m_dwRecordPerBlock; i++)
		{
			DWORD	dwPos	= bheader.m_dwPosFirstRecord + i * m_header.m_dwDataRecordSize;
			//if ((int)m_file.tellp() != dwPos)
			m_file.seekp(dwPos, fstream::beg);
			int wBytes1=m_file.tellp();
// 			FILE* fp=fopen(m_filename.c_str(),"r+b");
// 			if (fp)
// 			{
// 				fseek(fp,wBytes1,SEEK_SET);
// 				fwrite(((char *)pData)+dwDataElementSize*dwCount, min(dwDataElementSize,m_header.m_dwDataRecordSize),1,fp);
// 				fclose(fp);
// 			}
			int dataBytes=min(dwDataElementSize,m_header.m_dwDataRecordSize);
// 			m_file.seekp(dataBytes,fstream::cur);
// 			m_file.seekp((int)m_file.tellp()-dataBytes,fstream::beg);
			m_file.write(((char *)pData)+dwDataElementSize*dwCount, dataBytes);
			
			int wBytes=(int)m_file.tellp()-wBytes1;
			dwCount ++;
			if (dwCount >= dwDataElementCount)
				break;
		}
		m_file.flush();
		// 修改Block Header
		bheader.m_bUsed	= true;
		bheader.m_dwDataRecordCount	+= (dwCount-dwCountOld);
		bheader.m_dwPosNextBlock	= -1;
		if (dwCount < dwDataElementCount)
			bheader.m_dwPosNextBlock	= GetFirstBlankBlockPos(true, true);
		m_file.seekp(dwPosBlock, fstream::beg);
		m_file.write((char*)&bheader, sizeof(bheader));

		// 新Block
		dwPosBlock	= bheader.m_dwPosNextBlock;
	}

	if (bFlush)
		m_file.flush();
	
	return dwCount;
}

//=============================================================================
// CSelfDB

CSelfDB::CSelfDB(const char * rootpath, bool bOK) : CQianlong(rootpath, bOK)
{
}

CSelfDB::~CSelfDB()
{
}

bool CSelfDB::GetFileName(string& sFileName, int nDataType, instrument_info* pInfo, int nKType)
{
	if (nDataType == instrument::dataOutline)
	{
		sFileName = GetRootPath();
		sFileName += self_outline;
		return true;
	}

	if (pInfo==  NULL || !pInfo->is_valid())
		return false;

	// 如果钱龙文件存在，就返回钱龙文件名
	string sFileNameQL;
	if (instrument::dataDR != nDataType
		&& CQianlong::GetFileName(sFileNameQL, nDataType, pInfo, nKType)
		&& access(sFileNameQL.c_str(),0) == 0)
	{
		sFileName = sFileNameQL;
		return true;
	}

	// 确定市场类型
	//if (pInfo->GetMarket() == CInstrument::marketUnknown)
	//	pInfo->ResolveTypeAndMarket();

	// 如果在 ml_sh 目录下找到文件，就返回找到的文件名
	// 否则，若钱龙文件名长度大于0，就返回钱龙文件名，等于0就返回 ml_sh 下的文件名
	if (nDataType == instrument::dataBasetext)
	{
		sFileName = GetRootPath();
		sFileName += ml_sh_base;
		sFileName += string(pInfo->get_id()) + ml_ext_base;
		if (access(sFileName.c_str(), 0) != 0 && sFileNameQL.length() > 0)
			sFileName = sFileNameQL;

		return true;
	}
	else if (nDataType == instrument::dataK)
	{
		sFileName = GetRootPath();
		sFileName += ml_sh;

		switch (nKType)
		{
		case ktypeMonth:
			sFileName += string(ml_month) + pInfo->get_id() + ml_ext_month;
			break;
		case ktypeWeek:
			sFileName += string(ml_week) + pInfo->get_id() + ml_ext_week;
			break;
		case ktypeDay:
			sFileName += string(ml_day) + pInfo->get_id() + ml_ext_day;
			break;
		case ktypeMin60:
			return false;
		case ktypeMin30:
			return false;
		case ktypeMin15:
			return false;
		case ktypeMin5:
			sFileName += string(ml_min5) + pInfo->get_id() + ml_ext_min5;
			break;
		default:
			return false;
		}

		if (access(sFileName.c_str(), 0) != 0 && sFileNameQL.length() > 0)
			sFileName = sFileNameQL;

		return true;
	}
	else if (nDataType == instrument::dataDR)
	{
		sFileName = GetRootPath();
// 		if (pInfo->IsShenZhen())
// 			sFileName += self_sz_xdr;
// 		else
// 			sFileName += self_sh_xdr;
		sFileName += string(pInfo->get_id()) + self_ext_xdr;
		if (access(sFileName.c_str(), 0) == 0)
			return true;

		string sTemp = GetRootPath();
		sTemp += self_sh_xdr;
		sTemp += string(pInfo->get_id()) + self_ext_xdr;
		if (access(sTemp.c_str(),0) == 0)
			sFileName = sTemp;

		return true;
	}
	else if (nDataType == instrument::dataReport)
	{
		sFileName = GetRootPath();
// 		if (pInfo->IsShenZhen())
// 			sFileName += self_sz_report;
// 		else
 			sFileName += self_sh_report;

		return true;
	}
	else if (nDataType == instrument::dataMinute)
	{
		sFileName = GetRootPath();
		//if (pInfo->IsShenZhen())
		//	sFileName += self_sz_minute;
		//else
		//	sFileName += self_sh_minute;
		sFileName+=string("data\\minute.min");
		return true;
	}

	return false;
}

string CSelfDB::GetNewsPath(DWORD dwMarket)
{
	string	strPath	/*= AfxGetProfile().GetSelfDBPath()*/;
	strPath	+= self_news;
	return strPath;
}

string CSelfDB::GetBasePath(DWORD dwMarket)
{
	string	strPath	/*= AfxGetProfile().GetSelfDBPath()*/;
	switch (dwMarket)
	{
	case instrument::marketSHSE:
		strPath	+= ml_sh_base;
		break;
	case instrument::marketSZSE:
		strPath	+= ml_sz_base;
		break;
	default:
		strPath	+= ml_sh_base;
		assert(false);
	}
	return strPath;
}

bool CSelfDB::CreateSelfDB(const char * rootpath)
{
	if (NULL == rootpath || strlen(rootpath) == 0)
		return false;

	// get rootpath
	string	strRoot	= rootpath;
	int nLen = strRoot.length();
	if (strRoot[nLen-1] != '\\' && strRoot[nLen-1] != '/')
		strRoot	+= CHAR_DIRSEP;
	nLen	= strRoot.length();

	if (0 != access(strRoot.c_str(), 0))
		return false;

	if (0 != access((strRoot + ml_dat).c_str(), 0))
		_mkdir((strRoot + ml_dat).c_str());
	if (0 != access((strRoot + ml_data).c_str(), 0))
		_mkdir((strRoot + ml_data).c_str());

	if (0 != access((strRoot + ml_sh).c_str(), 0))
		_mkdir((strRoot + ml_sh).c_str());
	if (0 != access((strRoot + ml_sh_base).c_str(), 0))
		_mkdir((strRoot + ml_sh_base).c_str());
	if (0 != access((strRoot + ml_sh_month).c_str(), 0))
		_mkdir((strRoot + ml_sh_month).c_str());
	if (0 != access((strRoot + ml_sh_week).c_str(), 0))
		_mkdir((strRoot + ml_sh_week).c_str());
	if (0 != access((strRoot + ml_sh_day).c_str(), 0))
		_mkdir((strRoot + ml_sh_day).c_str());
	if (0 != access((strRoot + ml_sh_min).c_str(), 0))
		_mkdir((strRoot + ml_sh_min).c_str());
	if (0 != access((strRoot + self_sh_xdr).c_str(), 0))
		_mkdir((strRoot + self_sh_xdr).c_str());

	if (0 != access((strRoot + ml_sz).c_str(), 0))
		_mkdir((strRoot + ml_sz).c_str());
	if (0 != access((strRoot + ml_sz_base).c_str(), 0))
		_mkdir((strRoot + ml_sz_base).c_str());
	if (0 != access((strRoot + ml_sz_month).c_str(), 0))
		_mkdir((strRoot + ml_sz_month).c_str());
	if (0 != access((strRoot + ml_sz_week).c_str(), 0))
		_mkdir((strRoot + ml_sz_week).c_str());
	if (0 != access((strRoot + ml_sz_day).c_str(), 0))
		_mkdir((strRoot + ml_sz_day).c_str());
	if (0 != access((strRoot + ml_sz_min).c_str(), 0))
		_mkdir((strRoot + ml_sz_min).c_str());
	if (0 != access((strRoot + self_sz_xdr).c_str(), 0))
		_mkdir((strRoot + self_sz_xdr).c_str());

	if (0 != access((strRoot + self_news).c_str(), 0))
		_mkdir((strRoot + self_news).c_str());

	return true;
}

int LoadCodeTable(instrument_container& container,const char* lpszFileName, DWORD dwMarket)
{
	int nCount = 0;

	char seps[]   = ",\t\r\n";
	char quotation_mark[] = "\"";

	bool bHasQuotationMark = false;
	fstream	file;
	file.open(lpszFileName, fstream::in);
	if (file.is_open())
	{
		string	rString;
	//	while(file.ReadString(rString))
	//	{
	//		CInstrumentInfo	info;

	//		// 600000,浦发银行,17,PFYH,"PuFaYinHang"
	//		// 英文名称可以用双引号引起来
	//		int nToken = 0;
	//		while(!rString.IsEmpty())
	//		{
	//			nToken ++;

	//			CString sTemp;
	//			
	//			int nIndex = -1;
	//			if (5 == nToken && -1 != (nIndex=rString.Find(quotation_mark)))
	//			{
	//				rString = rString.Mid(nIndex+1);
	//				nIndex = rString.Find(quotation_mark);
	//				if (-1 != nIndex)	sTemp = rString.Left(nIndex);
	//				if (-1 != nIndex)	rString = rString.Mid(nIndex+1);
	//				nIndex = rString.FindOneOf(seps);
	//				if (-1 != nIndex)
	//					rString = rString.Mid(nIndex+1);
	//				else
	//					rString.Empty();
	//			}
	//			else
	//			{
	//				nIndex = rString.FindOneOf(seps);
	//				if (-1 != nIndex)
	//				{
	//					sTemp = rString.Left(nIndex);
	//					rString = rString.Mid(nIndex+1);
	//				}
	//				else
	//				{
	//					sTemp = rString;
	//					rString.Empty();
	//				}
	//			}

	//			if (1 == nToken)
	//				info.SetStockCode(dwMarket, sTemp);
	//			else if (2 == nToken)
	//				info.SetStockName(sTemp);
	//			else if (3 == nToken)
	//				info.SetType(atol(sTemp));
	//			else if (4 == nToken)
	//				info.SetStockShortName(sTemp);
	//			else if (5 == nToken)
	//			{
	//				info.SetStockNameEnu(sTemp);
	//				break;
	//			}
	//		}

	//		if (info.IsValidInstrument())
	//			container.Add(info);
	//		nCount ++;
	//	}

	//	file.Close();
	}

	return nCount;
}

int	CSelfDB::LoadCodetable(instrument_container& container)
{
	if (!m_bIsOK)	return 0;

	container.resize(2000);

	// 上海指数
	string	sFileName	= GetRootPath();
	sFileName	+= self_sh_code;
	LoadCodeTable(container, sFileName.c_str(), instrument::marketSHSE);

	// 深圳指数
	sFileName	= GetRootPath();
	sFileName	+= self_sz_code;
	LoadCodeTable(container, sFileName.c_str(), instrument::marketSZSE);
	
	if (container.size() <= 0)
		CQianlong::LoadCodetable(container);

	return container.size();
}

int	CSelfDB::StoreCodetable(instrument_container& container)
{
	
	if (!m_bIsOK)	return 0;

	if (container.size() <= 0)
		return 0;

	// 上海指数
	string	sFileNameSH	= GetRootPath();
	sFileNameSH	+= self_sh_code;

	// 深圳指数
	string	sFileNameSZ	= GetRootPath();
	sFileNameSZ	+= self_sz_code;
	
	fstream	fileSHSE, fileSZSE;

	fileSHSE.open(sFileNameSH.c_str(), fstream::out);
	fileSZSE.open(sFileNameSZ.c_str(), fstream::out);
	if (!fileSHSE.is_open()|| !fileSZSE.is_open() )
	{
		return 0;
	}

	container.lock();
	for (size_t i=0; i<container.size(); i++)
	{
		instrument_info & info = container.at(i);
		string	str;

		//str.Format("%s,%s,%d,%s,\"%s\"\r\n", info.GetStockCode(), info.GetStockNameChs(), info.GetType(),
		//				info.GetStockShortName(), info.GetStockNameEnu());

		//if (info.IsShangHai())
		//{
		//	fileSHSE.Write(str, str.GetLength());
		//}
		//if (info.IsShenZhen())
		//{
		//	fileSZSE.Write(str, str.GetLength());
		//}
	}
	container.unlock();

	return container.size();
}

int CSelfDB::LoadKData(instrument* pstock, int nKType)
{
	// WILLCHECK
	int ret = CQianlong::LoadKData(pstock, nKType);
	cout<<"CQianlong::LoadKData-->"<<ret<<std::endl;
	if (ktypeMin5 == nKType && LoadMinute(pstock) > 0)
	{
		kdata_container	& kdataMin5 = pstock->GetKDataMin5();
		minute_container & minute = pstock->GetMinute();
		kdata_container kdataNew;
		if (minute.ToKData(kdataNew) && ktypeMin5 == kdataNew.GetKType())
		{
			kdataMin5.MergeKData(&kdataNew);
		}
		cout<<"CQianlong::LoadKData-->LoadMinute"<<kdataMin5.size()<<std::endl;
		return kdataMin5.size();
	}
	return ret;
}

int CSelfDB::LoadBasetable(instrument_container& container)
{
	container.lock();

	std::map<std::string,void* >	map;
	//map.InitHashTable(container.GetSize() + container.GetSize() + 100);

	for (size_t i=0; i<container.size(); i++)
	{
		instrument_info	& info	= container.at(i);
		map.insert(make_pair(string(info.get_id()), (void *)i));
		info.m_basedata.clear();
	}
	
	string	sFileName	= GetRootPath();
	sFileName	+= self_chna_basetbl;
	std::fstream	file;
	file.open(sFileName.c_str(), std::fstream::in);
	if (file.is_open())
	{
		BASEDATA	block;
		while(/*sizeof(block) == */file.read((char*)&block, sizeof(block)))
		{
			void * pArrayID	= NULL;
			std::map<std::string,void* >::iterator it=map.find(string(block.szCode));
			if (map.end()!=it)
			{
				pArrayID=it->second;
                int	nIndex	= ((intptr_t)pArrayID);
				if (nIndex >= 0 && nIndex < container.size())
				{
					container.at(nIndex).m_basedata.InsertBaseDataSort(block);
				}
			}
			else
			{
				instrument_container::update(container,&block,true);
			}
		}
		file.close();
	}
	container.unlock();
	return container.size();
}

int CSelfDB::StoreBasetable(instrument_container& container)
{
	assert(m_bIsOK && container.size() > 0);
	if (!m_bIsOK || container.size() <= 0)	return 0;

	int	nCount	= 0;
	std::string	sRoot		= GetRootPath();
	std::string	sFileName	= sRoot + self_sh_code;

	container.lock();
	std::fstream	file;
	file.open(sFileName.c_str(),std::ios::out|std::ios::binary);
	if (file.is_open())
	{
 		for (size_t i=0; i<container.size(); i++)
		{
			instrument_info	& info = container.at(i);
			for (size_t k=0; k<info.m_basedata.size(); k++)
			{
				BASEDATA & block = info.m_basedata.at(k);
				if (k == info.m_basedata.size() - 1)
				{
					//block.m_fYield_average	= info.m_fYield_average;
					//block.m_fYield_stddev	= info.m_fYield_stddev;
					//block.m_fBeite			= info.m_fBeite;
				}
				file.write((char*)&block, sizeof(block));
			}
			nCount	++;
		}
	}
	file.close();
	container.unlock();
	return nCount;
}

int CSelfDB::LoadDRData(instrument* pstock)
{
	assert(m_bIsOK && pstock && pstock->GetInstrumentInfo().is_valid());
	if (!m_bIsOK || !pstock || !pstock->GetInstrumentInfo().is_valid())	return 0;

	string	sFileName;
	GetFileName(sFileName, instrument::dataDR, &(pstock->GetInstrumentInfo()));
	
	//CDRData	&	drdata = pstock->GetDRData();

	//DWORD	dwMarket	= pstock->GetInstrumentInfo().GetMarket();
	//CString	sCode	= pstock->GetStockCode();
	fstream	file;
	file.open(sFileName.c_str(), fstream::in);
	if (file.is_open())
	{
		DWORD dwLen = 0/*file.GetLength()*/;
		CLK_DRDATA	dbdr;
		int	nSize	= dwLen/sizeof(dbdr);
		//drdata.SetSize(0, nSize);

		while(/*sizeof(dbdr) ==*/ file.read((char*)&dbdr, sizeof(dbdr)))
		{
			DRDATA	dr;
			//if (convert_CLK_DRDATA_to_DRDATA(dwMarket, sCode, &dbdr, &dr))
			//	drdata.InsertDRDataSort(dr);
		}

		file.close();
		//return drdata.GetSize();
	}

	// Load From FXJ_DRDATA
	sFileName	= GetRootPath();
	sFileName	+= self_chna_xdr;
	WORD	wFxjMarket	= 'HS';
	//if (CInstrument::marketSZSE == dwMarket)
	//	wFxjMarket	= 'ZS';
	file.open(sFileName.c_str(), fstream::in);
	if (file.is_open())
	{
		file.seekg(8, fstream::beg);
		if (8 == (int)file.tellg())
		{
			bool	bMy	= false;
			FXJ_DRDATA	fxjdr;
			while(/*sizeof(fxjdr) == */file.read((char*)&fxjdr, sizeof(fxjdr)))
			{
				bool	bMyOld	= bMy;
				if (-1 == fxjdr.m_dwMagic)
				{
					//bMy	= (fxjdr.m_wMarket == wFxjMarket && 
					//0 == strncmp(sCode, fxjdr.m_szCode, min(sizeof(fxjdr.m_szCode),sCode.GetLength())));
				}
				else if (bMy)
				{
					DRDATA	dr;
					//if (convert_FXJ_DRDATA_to_DRDATA(dwMarket, sCode, &fxjdr, &dr))
					//	drdata.InsertDRDataSort(dr);
				}
				if (bMyOld && !bMy)
					break;
			}
		}
	}
	return 1;
	//return drdata.GetSize();
}

int CSelfDB::StoreDRData(instrument* pstock)
{
	assert(m_bIsOK && pstock && pstock->GetInstrumentInfo().is_valid());
	if (!m_bIsOK || !pstock || !pstock->GetInstrumentInfo().is_valid())	return 0;

	string	sFileName;
	GetFileName(sFileName, instrument::dataDR, &(pstock->GetInstrumentInfo()));
	
	//CDRData	&	drdata = pstock->GetDRData();

	//if (drdata.GetSize() == 0)
	//{
	//	::DeleteFile(sFileName);
	//	return 0;
	//}

	// Compare
	instrument	stocktemp;
	//stocktemp.SetStockInfo(&(pstock->GetInstrumentInfo()()));
	//if (LoadDRData(&stocktemp) > 0 && stocktemp.GetDRData().IsSameAs(&drdata))
	//	return drdata.GetSize();

	// Store
	fstream	file;
	file.open(sFileName.c_str(), fstream::in|fstream::out);
	if (file.is_open())
	{
		//for (int i=0; i<drdata.GetSize(); i++)
		//{
		//	CLK_DRDATA	dbdr;
		//	convert_DRDATA_to_CLK_DRDATA(&(drdata.ElementAt(i)), &dbdr);
		//	file.Write(&dbdr, sizeof(dbdr));
		//}
	}
	return 1;
//	return drdata.GetSize();
}

DWORD ReadReport(instrument* pstock,const char* lpszFileName)
{
	
	assert(pstock && pstock->GetInstrumentInfo().is_valid());
	if (!pstock || !pstock->GetInstrumentInfo().is_valid())
		return 0;

	report_container& aReport = pstock->GetReport();
	aReport.clear();

	CTSKFile file;
	if (file.Open(lpszFileName))
	{
		DWORD dwDataRecordCount	= file.GetDataRecordCount(pstock->GetInstrumentInfo().szExchange, pstock->GetInstrumentInfo().szCode);
		aReport.resize(dwDataRecordCount);
		DWORD dwCount = file.LoadDataRecord(pstock->GetInstrumentInfo().ExchangeID, pstock->GetInstrumentInfo().szCode, aReport.data(), sizeof(Tick), dwDataRecordCount);
		aReport.resize(dwCount);

		aReport.sort();
		int nOldSize = aReport.size();
		//aReport.RemoveDirty();
		if (nOldSize - aReport.size() > 50)
		{
			assert(aReport.size() == (int)file.StoreDataRecord(pstock->GetInstrumentInfo().ExchangeID, pstock->GetInstrumentID(),
				aReport.data(), sizeof(Tick), aReport.size(), true));
		}
	}

	return aReport.size();
}

int CSelfDB::LoadReport(instrument* pstock)
{
	//std::unique_lock<std::mutex> slock(m_mutex);
	assert(m_bIsOK && pstock && pstock->GetInstrumentInfo().is_valid());
	if (!m_bIsOK || !pstock || !pstock->GetInstrumentInfo().is_valid())
		return 0;

	pstock->GetReport().clear();

	string sFileName;
	assert(GetFileName(sFileName, instrument::dataReport, &(pstock->GetInstrumentInfo())));
	ReadReport(pstock, sFileName.c_str());

	return pstock->GetReport().size();
}

int CSelfDB::LoadMinute(instrument* pstock)
{
	//std::unique_lock<std::mutex> slock(m_mutex);
	assert(m_bIsOK && pstock && pstock->GetInstrumentInfo().is_valid());
	if (!m_bIsOK || !pstock || !pstock->GetInstrumentInfo().is_valid())
		return 0;

	pstock->GetMinute().clear();

	string sFileName;
	assert(GetFileName(sFileName, instrument::dataMinute, &(pstock->GetInstrumentInfo())));
	cout<<"CSelfDB::LoadMinute-->ReadMinute-->begin"<<std::endl;
	ReadMinute(pstock, sFileName.c_str());
	cout<<"CSelfDB::LoadMinute-->ReadMinute-->end"<<std::endl;
	return pstock->GetMinute().size();
}

int CSelfDB::LoadOutline(instrument* pstock)
{
	return  0;
	//ASSERT(m_bIsOK && pstock && pstock->GetInstrumentInfo().IsValidInstrument());
	//if (!m_bIsOK || !pstock || !pstock->GetInstrumentInfo().IsValidInstrument())	return 0;

	//COutline	& aOutline	= pstock->GetOutline();
	//aOutline.RemoveAll();

	//CString	sFileName;
	//VERIFY(GetFileName(sFileName, CInstrument::dataOutline, &(pstock->GetInstrumentInfo()())));

	//CFile		file;
	//if (file.Open(sFileName, CFile::modeRead))
	//{
	//	OUTLINE outline;
	//	aOutline.SetSize(aOutline.GetSize(), file.GetLength()/sizeof(outline) + 10);
	//	while(sizeof(outline) == file.Read(&outline,sizeof(outline)))
	//		aOutline.Add(outline);
	//}

	//return aOutline.GetSize();
}

int	CSelfDB::StoreReport(Tick* pReport, int nCount, bool bBigTrade)
{
	//std::unique_lock<std::mutex> slock(m_mutex);
	assert(m_bIsOK && pReport && nCount > 0);
	if (!m_bIsOK || !pReport || nCount <= 0)
		return 0;

	static bool	bFirstCall	= true;
	if (bFirstCall)
	{
		bFirstCall	= false;
		// remove old
		string	sRoot	= GetRootPath();
		CTSKFile::RemoveFileIfOutoftime((sRoot+self_sh_report).c_str(), pReport->UpdateTime);
		CTSKFile::RemoveFileIfOutoftime((sRoot+self_sz_report).c_str(), pReport->UpdateTime);
	}

	string	sFileName;
	CTSKFile	file;
	DWORD	dwStoreCount	= 0;
	for (int i=0; i<nCount; i++)
	{
		instrument_info	info;
		string	sFileNameNew;
		if (!info.set_id(pReport[i].ExchangeID, pReport[i].szCode)
			|| !GetFileName(sFileNameNew, instrument::dataReport, &info))
			continue;

		if (0 != sFileNameNew.compare(sFileName))
		{
			sFileName	= sFileNameNew;
			assert(CTSKFile::BuildEmptyFile(sFileName.c_str(), instrument::dataReport, pReport->ExchangeID, 300, 125, false));
			assert(file.Open(sFileName.c_str()));
		}
		//store
		if (bBigTrade)
		{
			dwStoreCount += file.StoreDataRecord(	pReport[i].ExchangeID, "000000",
				&(pReport[i]), sizeof(Tick), 1, false);
		}
		else
		{
			dwStoreCount += file.StoreDataRecord(	pReport[i].ExchangeID, pReport[i].szCode,
				&(pReport[i]), sizeof(Tick), 1, false);
		}
	}

	return dwStoreCount;
}

int	CSelfDB::StoreMinute(MINUTE* pMinute, int nCount)
{
	//std::unique_lock<std::mutex> slock(m_mutex);
	cout<<"CSelfDB::StoreMinute-->begin"<<std::endl;
	assert(m_bIsOK && pMinute && nCount > 0);
	if (!m_bIsOK || !pMinute || nCount <= 0)
		return 0;

	static bool bFirstCall = true;
	if (bFirstCall)
	{
		bFirstCall = false;
		std::string sRoot = GetRootPath();
		CTSKFile::RemoveFileIfOutoftime((sRoot + self_sh_minute).c_str(), pMinute->TradingTime);
		CTSKFile::RemoveFileIfOutoftime((sRoot + self_sz_minute).c_str(), pMinute->TradingTime);
	}
	std::string sFileName;
	CTSKFile file;
	DWORD dwStoreCount = 0;
	minute_container aMinute;
	for (int i = 0; i < nCount; i++)
	{
		instrument_info info;
		std::string sFileNameNew;
		//从合约列表中查询交易所ID;
		if (strlen(pMinute[i].szExchange)<=0)
		{
			strcpy(pMinute[i].szExchange,instrument_container::get_instance().GetExhcnageIDByInstrumentID(pMinute[i].szCode));
		}
		bool b1=!info.set_id(pMinute[i].szExchange, pMinute[i].szCode);
		bool b2=!GetFileName(sFileNameNew, instrument::dataMinute, &info);
		if (b1||b2 )
			continue;
		if (sFileNameNew.compare(sFileName) != 0)
		{
			sFileName = sFileNameNew;
			(CTSKFile::BuildEmptyFile(sFileName.c_str(), instrument::dataMinute, 
				pMinute->szExchange, 300, 20, false));
			(file.Open(sFileName.c_str()));
		}
		if (aMinute.size() > 0 && (strcmp(aMinute[0].szExchange,pMinute[i].szExchange)!=0
			|| strncmp(aMinute[0].szCode,pMinute[i].szCode, sizeof(pMinute[i].szCode))) != 0)
		{
			dwStoreCount++;

			file.StoreDataRecord(aMinute[0].szExchange, aMinute[0].szCode, aMinute.data(), sizeof(MINUTE), aMinute.size(), false);
			aMinute.clear();
		}
		aMinute.add(pMinute[i]);
	}

	if (aMinute.size() > 0)
	{
		dwStoreCount++;
		cout<<"CSelfDB::StoreMinute-->StoreDataRecord-->begin"<<std::endl;
		file.StoreDataRecord(aMinute[0].szExchange, aMinute[0].szCode, aMinute.data(), sizeof(MINUTE), aMinute.size(), false);
		cout<<"CSelfDB::StoreMinute-->StoreDataRecord-->end"<<std::endl;
		aMinute.clear();
	}

	return dwStoreCount;
}

int	CSelfDB::StoreOutline(OUTLINE * pOutline, int nCount)
{
	assert(m_bIsOK && pOutline && nCount > 0);
	if (!m_bIsOK || !pOutline || nCount <= 0)	return 0;

	string	sFileName;
	(GetFileName(sFileName,instrument::dataOutline,NULL));
	
	fstream	file;
	file.open(sFileName.c_str(), fstream::out);
	if (file.is_open())
	{
		file.write((char*)pOutline, sizeof(OUTLINE)*nCount);
		file.close();
		return nCount;
	}
	return 0;
}

bool CSelfDB::GetAccurateRoot(const char * rootpath, char *accurateroot, int maxlen)
{
	if (0 == rootpath || strlen(rootpath)==0)
		return false;
	std::string	strRoot	= rootpath;
	int nLen = strRoot.length();
	if (strRoot[nLen-1] != L'\\' && strRoot[nLen-1] != L'/')
		strRoot	+= CHAR_DIRSEP;
	nLen = strRoot.length();
	if (0 != access((strRoot + ml_dat).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_dat).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_data).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_data).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_sh).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_sh).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_sh_base).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_sh_base).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_sh_month).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_sh_month).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_sh_week).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_sh_week).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_sh_day).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_sh_day).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + ml_sh_min).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + ml_sh_min).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + self_sh_xdr).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + self_sh_xdr).c_str()))
		{
			return false;
		}
	}
	if (0 != access((strRoot + self_news).c_str(), 0))
	{
		if(0!=_mkdir((strRoot + self_news).c_str()))
		{
			return false;
		}
	}
	strncpy(accurateroot, strRoot.c_str(), maxlen-1);
	accurateroot[maxlen-1]	= '\0';
	return true;
}

int CSelfDB::InstallCodetbl(const char * filename, const char *orgname)
{
	if (NULL == filename || strlen(filename) == 0
		|| NULL == orgname || strlen(orgname) == 0)
		return 0;

	std::string	sFileName	= GetRootPath();

	std::string	sOrgName = "dat\\";
	sOrgName	+= orgname;
	if (1/*0 == sOrgName.CompareNoCase(ml_sh_info)
		|| 0 == sOrgName.CompareNoCase(ml_sz_info)
		|| 0 == sOrgName.CompareNoCase(ml_sh_now)
		|| 0 == sOrgName.CompareNoCase(ml_sz_now)
		|| 0 == sOrgName.CompareNoCase(ml_sh_pyjc)
		|| 0 == sOrgName.CompareNoCase(ml_sz_pyjc)
		|| 0 == sOrgName.CompareNoCase(ml_sh_trace)
		|| 0 == sOrgName.CompareNoCase(ml_sz_trace)
		|| 0 == sOrgName.CompareNoCase(ml_sh_minute)
		|| 0 == sOrgName.CompareNoCase(ml_sz_minute)*/)
		sFileName	+= ml_dat;
	else
		sFileName	+= ml_data;

	sFileName	+= orgname;
	return 1;
	//return CFile::CopyFile(filename, sFileName, false);
}

int CSelfDB::InstallCodetblBlock(const char * filename, const char *orgname)
{
	if (NULL == filename || strlen(filename) == 0
		|| NULL == orgname || strlen(orgname) == 0)
		return 0;

	int nRet = 0;
// 	CDomainContainer newdomains;
// 	if (newdomains.Load(CString(filename)))
// 	{
// 		nRet = AfxGetDomainContainer().AddDomainReplace(newdomains);
// 		//AfxGetDomainContainer().Store(AfxGetProfile().GetDomainFile());
// 	}
	return nRet;
}

int CSelfDB::InstallCodetblFxjBlock(const char * filename, const char *orgname)
{
	if (NULL == filename || strlen(filename) == 0
		|| NULL == orgname || strlen(orgname) == 0)
		return 0;
	return 0;
// 	string	sName	= orgname;
// 	int nIndex = sName.Find('.');
// 	if (-1 != nIndex)
// 		sName	= sName.Left(nIndex);
// 	CDomain	domain;
// 	domain.m_strName = sName;
// 	int nRet = domain.AddFxjDomain(CString(filename));
// 	if (nRet > 0)
// 	{
// 		AfxGetDomainContainer().AddDomainReplace(domain);
// 	}
// 	return nRet;
}

// int CSelfDB::InstallDRData(CDRData & drdata)
// {
// 	if (drdata.GetSize() <= 0)
// 		return 0;
// 
// 	CString	sFileName;
// 	CInstrumentInfo	stockinfo;
// 	DWORD	dwMarket	= drdata.ElementAt(0).m_dwMarket;
// 	CString	sCode	= drdata.ElementAt(0).m_szCode;
// 	//stockinfo.SetStockCode(dwMarket, sCode);
// 	if (!GetFileName(sFileName, CInstrument::dataDR, &stockinfo))
// 		return 0;
// 
// 	int	nCount	= 0;
// 
// 	CFile	fileTo;
// 	if (fileTo.Open(sFileName, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite))
// 	{
// 		for (int i=0; i<drdata.GetSize(); i++)
// 		{
// 			CLK_DRDATA	dbdrnew;
// 			convert_DRDATA_to_CLK_DRDATA(&(drdata.ElementAt(i)), &dbdrnew);
// 			
// 			fileTo.SeekToBegin();
// 			CLK_DRDATA	dbdr;
// 			memset(&dbdr, 0, sizeof(dbdr));
// 			bool	bHas	= false;
// 			bool	bInsert	= false;
// 			while(sizeof(dbdr) == fileTo.Read(&dbdr, sizeof(dbdr)))
// 			{
// 				if (dbdr.date == dbdrnew.date)
// 				{
// 					bHas	= true;
// 					fileTo.Seek(fileTo.GetPosition()-sizeof(dbdr), CFile::begin);
// 					break;
// 				}
// 				if (dbdr.date > dbdrnew.date)
// 				{
// 					bInsert	= true;
// 					break;
// 				}
// 			}
// 			if (bHas || !bInsert)
// 				fileTo.Write(&dbdrnew, sizeof(dbdrnew));
// 			else if (bInsert)
// 			{
// 				int nCur = fileTo.GetPosition();
// 				int nLen = fileTo.GetLength();
// 				BYTE * pbuffer = new BYTE[nLen-nCur+1];
// 				if (pbuffer)
// 				{
// 					if (nLen - nCur > 0)	fileTo.Read(pbuffer, nLen-nCur);
// 					fileTo.Seek(nCur-sizeof(dbdr), CFile::begin);
// 					fileTo.Write(&dbdrnew, sizeof(dbdrnew));
// 					fileTo.Write(&dbdr, sizeof(dbdr));
// 					if (nLen - nCur > 0)	fileTo.Write(pbuffer, nLen-nCur);
// 					delete [] pbuffer;
// 				}
// 			}
// 			nCount	++;
// 			fileTo.Flush();
// 		}
// 		fileTo.Close();
// 	}
// 	return nCount;
// }

int CSelfDB::InstallDRDataClk(const char * filename, const char *orgname)
{
	return 0;
// 	if (NULL == filename || strlen(filename) == 0
// 		|| NULL == orgname || strlen(orgname) == 0)
// 		return 0;
// 
// 	string	sFileName;
// 	string	sCode	= orgname;
// 	int nIndex = sCode.Find('.');
// 	if (-1 != nIndex)
// 		sCode	= sCode.Left(nIndex);
// 
// 	CInstrumentInfo	info;
// 	//info.SetStockCode(CInstrument::marketUnknown, sCode);
// 	//DWORD dwMarket = info.GetMarket();
// 
// 	CDRData	drdata;
// 	CFile	file;
// 	if (file.Open(CString(filename), CFile::modeRead))
// 	{
// 		CLK_DRDATA	dbdr;
// 		while(sizeof(dbdr) == file.Read(&dbdr,sizeof(dbdr)))
// 		{
// 			DRDATA	dr;
// 			//convert_CLK_DRDATA_to_DRDATA(dwMarket, sCode, &dbdr, &dr);
// 			drdata.Add(dr);
// 		}
// 		file.Close();
// 	}
// 	return InstallDRData(drdata);
}

int CSelfDB::InstallDRDataFxj(const char * fxjfilename)
{
	if (NULL == fxjfilename || strlen(fxjfilename) == 0)
		return 0;

	string	sFileName	= GetRootPath();
	sFileName	+= self_chna_xdr;
	
	return 1;
	//return CFile::CopyFile(fxjfilename, sFileName, false);
}

int CSelfDB::InstallBasetable(const char * filename, const char * orgname)
{
	if (NULL == filename || strlen(filename) == 0
		|| NULL == orgname || strlen(orgname) == 0)
		return 0;
	
	string	sFileName	= GetRootPath();
	sFileName	+= ml_data;
	sFileName	+= orgname;
	return 1;
	//return CFile::CopyFile(filename, sFileName, false);
}

int CSelfDB::InstallBasetableTdx(const char * filename)
{
	if (NULL == filename || strlen(filename) == 0)
		return 0;
	
	int	nCount	= 0;

	string	sRoot		= GetRootPath();
	string	sFileNameSHSZ	= sRoot + self_chna_basetbl;
// 	CFile	fileSHSZ, fileTdx;
// 	if (fileSHSZ.Open(sFileNameSHSZ, CFile::modeWrite | CFile::modeCreate)
// 		&& fileTdx.Open(CString(filename), CFile::modeRead))
// 	{
// 		fileTdx.Seek(TDX_FHEADER_SIZE, CFile::begin);
// 
// 		TDX_BASEDATA	tdxblock;
// 		while(sizeof(tdxblock) == fileTdx.Read(&tdxblock, sizeof(tdxblock)))
// 		{
// 			BASEDATA	block;
// 			if (convert_TDX_BASEDATA_to_BASEDATA(&tdxblock, &block))
// 			{
// 				fileSHSZ.Write(&block, sizeof(block));
// 				nCount	++;
// 			}
// 		}
// 	}

	return nCount;
}

int CSelfDB::InstallBasetableFxj(const char * filename)
{
	if (NULL == filename || strlen(filename) == 0)
		return 0;

// 	DWORD	dwDate = CSPTime::GetCurrentTime().ToInstrumentTimeDay();
// 	{
// 		string	sTemp = filename;
// 		int index1 = sTemp.rfind('/');
// 		int index2 = sTemp.rfind('\\');
// 		int index = max(index1,index2);
// 		if (index > 0)
// 			sTemp = sTemp.substr(index+1);
// 		DWORD	dwTemp = atol(sTemp);
// 		CSPTime	sptime;
// 		if (sptime.FromInstrumentTimeDay(dwTemp))
// 			dwDate = dwTemp;
// 	}
// 	
// 	int	nCount	= 0;
// 
// 	string	sRoot		= GetRootPath();
// 	string	sFileNameSHSZ	= sRoot + self_chna_basetbl;
// 	fstream	fileSHSZ, fileFxj;
// 	fileSHSZ.open(sFileNameSHSZ, fstream::out);
// 	fileFxj.open((filename), fstream::in);
// 	if ( fileSHSZ.is_open()&& fileFxj.is_open() )
// 	{
// 		fileFxj.seekg(FXJ_FHEADER_SIZE,fstream::beg);
// 
// 		FXJ_BASEDATA	fxjblock;
// 		while(/*sizeof(fxjblock) ==*/ fileFxj.read((char*)&fxjblock, sizeof(fxjblock)))
// 		{
// 			BASEDATA	block;
// 			if (convert_FXJ_BASEDATA_to_BASEDATA(&fxjblock, &block, dwDate))
// 			{
// 				fileSHSZ.write((char*)&block, sizeof(block));
// 				nCount	++;
// 			}
// 		}
// 	}
//
//	return nCount;
	return 0;
}

int CSelfDB::InstallNewsText(const char * filename, const char *orgname)
{
	if (NULL == filename || strlen(filename) == 0
		|| NULL == orgname || strlen(orgname) == 0)
		return 0;
	
	string	sFileName	= GetRootPath();
	sFileName	+= self_news;
	sFileName	+= orgname;
	return 1;
	//return CFile::CopyFile(filename, sFileName, false);
}

int CSelfDB::InstallNewsText(const char * buffer, int nLen, const char *orgname)
{
	if (NULL == buffer || nLen <= 0
		|| NULL == orgname || strlen(orgname) == 0)
		return 0;
	
	string	sFileName	= GetRootPath();
	sFileName	+= self_news;
	sFileName	+= orgname;

	fstream	file;
	file.open(sFileName.c_str(),fstream::in);
	if (file.is_open())
	{
		file.write(buffer, nLen);
		file.close();
		return 1;
	}
	return 0;
}

char CSelfDB::m_szDataType[]	=	"MiningVictory";

